using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Input.Touch;
using Risiko.Menu;


namespace Risiko.Rendering
{
  /// <summary>
  /// Questo è un componente del gioco che implementa IUpdateable.
  /// </summary>
  public abstract class UIRenderer : MainGameRenderer
  {
    private Vector2 cardsPosition;
    private int CARD_WIDTH, CARD_HEIGHT;
    private Rectangle reinfNumRect;
    private Rectangle playerInfoStartRect;
    protected Button nextBtn, menuBtn, confirmBtn, declineBtn;

    public UIRenderer(Game game)
      : base(game)
    {
      // TODO: creare qui eventuali componenti figlio
    }

    /// <summary>
    /// Consente al componente del gioco di eseguire l'inizializzazione necessaria prima dell'inizio
    /// dell'esecuzione. Qui è possibile eseguire query per eventuali servizi necessari e caricare contenuto.
    /// </summary>
    public override void Initialize()
    {
      CARD_WIDTH = 74;
      CARD_HEIGHT = 110;
      nextBtn = new Button() { spriteFont = Game.Content.Load<SpriteFont>("small_font"), bounds = new Rectangle(530, 400, 80, 50), color = Color.Red, message = "Next", textColor = Color.White, scale = 1.0f };
      menuBtn = new Button() { spriteFont = Game.Content.Load<SpriteFont>("small_font"), bounds = new Rectangle(150, 400, 80, 50), color = Color.Red, message = "Menu", textColor = Color.White, scale = 1.0f };
      confirmBtn = new Button() { spriteFont = Game.Content.Load<SpriteFont>("small_font"), bounds = new Rectangle(300, 200, 80, 50), color = Color.Red, message = "Yes", textColor = Color.White, scale = 1.0f };
      declineBtn = new Button() { spriteFont = Game.Content.Load<SpriteFont>("small_font"), bounds = new Rectangle(500, 200, 80, 50), color = Color.Red, message = "No", textColor = Color.White, scale = 1.0f };

      base.Initialize();

      cardsPosition = new Vector2(gameBounds.Width - 100, 10);
      reinfNumRect = new Rectangle(gameBounds.X, gameBounds.Height - 50, 50, 50);
      playerInfoStartRect = new Rectangle(gameBounds.X, gameBounds.Y, 120, 50);
    }


    protected override void LoadContent()
    {
      base.LoadContent();

      nextBtn.texture = whitePx;
      nextBtn.spriteFont = font;
      menuBtn.spriteFont = font;
      menuBtn.texture = whitePx;
      confirmBtn.texture = whitePx;
      confirmBtn.spriteFont = font;
      declineBtn.texture = whitePx;
      declineBtn.spriteFont = font;
    }


    /// <summary>
    /// Consente al componente del gioco di aggiornare se stesso.
    /// </summary>
    /// <param name="gameTime">Fornisce uno snapshot dei valori di temporizzazione.</param>
    public override void Update(GameTime gameTime)
    {
      base.Update(gameTime);
    }


    public override void UpdateUI(GameTime gameTime)
    {
      foreach (var g in cachedGestures)
      {
        switch (g.GestureType)
        {
          case GestureType.Tap:
            if (menuBtn.IsInBounds(new Point((int)g.Position.X, (int)g.Position.Y)))
              TouchedMenuBtn = true;
            break;
        }
      }
    }


    public override void UpdateAttack(GameTime gameTime)
    {
      // If two territories are selected, deselect them
      //if (selectedTerritories.Count >= 2)
      //{
      //  selectedTerritories.ForEach(tRef =>
      //  {
      //    gameState.board.continents[tRef.continentID].territories[tRef.territoryID].isSelected = false;
      //  });
      //  selectedTerritories.Clear();
      //}

      foreach (var g in cachedGestures)
      {

        switch (g.GestureType)
        {
          case GestureType.Tap:
            if (nextBtn.IsInBounds(new Point((int)g.Position.X, (int)g.Position.Y)))
              TouchedNextBtn = true;
            break;
          case GestureType.DoubleTap:
            break;
        }
      }

      base.UpdateAttack(gameTime);
    }


    public override void UpdateConquerMove(GameTime gameTime)
    {
      foreach (var g in cachedGestures)
      {
        switch (g.GestureType)
        {
          case GestureType.Tap:
            if (nextBtn.IsInBounds(new Point((int)g.Position.X, (int)g.Position.Y)))
              TouchedNextBtn = true;
            break;
          case GestureType.DoubleTap:
            break;
        }
      }

      base.UpdateConquerMove(gameTime);
    }

    public override void UpdateStrategicMove(GameTime gameTime)
    {
      foreach (var g in cachedGestures)
      {

        switch (g.GestureType)
        {
          case GestureType.Tap:
            if (nextBtn.IsInBounds(new Point((int)g.Position.X, (int)g.Position.Y)))
              TouchedNextBtn = true;
            break;
          case GestureType.DoubleTap:
            break;
        }
      }

      base.UpdateStrategicMove(gameTime);
    }

    public override void UpdateCardsConfirmation(GameTime gameTime)
    {
      foreach (var g in cachedGestures)
      {
        switch (g.GestureType)
        {
          case GestureType.Tap:
            if (confirmBtn.IsInBounds(new Point((int)g.Position.X, (int)g.Position.Y)))
              TouchedConfirmBtn = true;
            if (declineBtn.IsInBounds(new Point((int)g.Position.X, (int)g.Position.Y)))
              TouchedDeclineBtn = true;
            break;
        }
      }
      
    }

    public override void Draw(GameTime gameTime)
    {
      base.Draw(gameTime);
    }

    public override void DrawUI(GameTime gameTime)
    {
      // Draw User Interface elements

      // Draw player info
      var currentPlayer = gameState.playerStates[(int)gameState.currentPlayer];
      string playing = "Playing: " + currentPlayer.name;
      spriteBatch.DrawString(font, playing, new Vector2(Game.GraphicsDevice.Viewport.Bounds.Center.X - (font.MeasureString(playing).X / 2), 10), currentPlayer.color);

      // Legenda giocatori
      var playerInfo = playerInfoStartRect;
      Color currentColor;
      for (int i = 0; i < gameState.playerStates.Length; ++i)
      {
        if (i == (int)gameState.currentPlayer)
          currentColor = Color.Orange;
        else
          currentColor = Color.Goldenrod;
        spriteBatch.Draw(whitePx, playerInfo, currentColor);
        DrawCenteredMsg(font, gameState.playerStates[i].name, new Vector2(playerInfo.Center.X, playerInfo.Center.Y) + Vector2.One, Color.Black, Vector2.One);
        DrawCenteredMsg(font, gameState.playerStates[i].name, new Vector2(playerInfo.Center.X, playerInfo.Center.Y), gameState.playerStates[i].color, Vector2.One);
        playerInfo.Offset(playerInfo.Width, 0);
        //spriteBatch.DrawString(font, gameState.playerStates[i].name, new Vector2(10, 350 + (i * 30)), gameState.playerStates[i].color);
      }

      // Buttons
      menuBtn.DrawCenteredButton(spriteBatch);

      // Reinforcements not yet assigned
      var reinfNum = gameState.playerStates[(int)gameState.currentPlayer].reinforcementsNum;
      if (reinfNum > 0)
      {
        spriteBatch.Draw(whitePx, reinfNumRect, gameState.playerStates[(int)gameState.currentPlayer].color);
        DrawCenteredMsg(font, reinfNum.ToString(), new Vector2(reinfNumRect.Center.X, reinfNumRect.Center.Y) + Vector2.One, Color.Black, Vector2.One);
        DrawCenteredMsg(font, reinfNum.ToString(), new Vector2(reinfNumRect.Center.X, reinfNumRect.Center.Y), Color.White, Vector2.One);
      }

      if (!(gameState.playerStates[(int)gameState.currentPlayer].isHuman))
        return;

      // FROM NOW ON, DRAW THINGS ONLY VISIBLE TO THE HUMAN PLAYER

      // Cards
      var cards = gameState.playerStates[(int)gameState.currentPlayer].Cards;
      for (int i = 0; i < cards.Count; ++i)
      {
        DrawCard(new Rectangle((int)cardsPosition.X + (i * 3), (int)cardsPosition.Y, CARD_WIDTH, CARD_HEIGHT), false);
      }
    }

    public override void DrawPlaceReinforcements(GameTime gameTime)
    {
      DrawCenteredMsg(font, "Piazzamento rinforzi", new Vector2(gameBounds.Center.X, gameBounds.Center.Y), Color.Red, Vector2.One);
      //nextBtn.DrawCenteredButton(spriteBatch);
      base.DrawPlaceReinforcements(gameTime);
    }

    public override void DrawAttack(GameTime gameTime)
    {
      DrawCenteredMsg(font, "Attacco", new Vector2(gameBounds.Center.X, gameBounds.Center.Y), Color.Red, Vector2.One);
      if (gameState.playerStates[(int)gameState.currentPlayer].isHuman)
        nextBtn.DrawCenteredButton(spriteBatch);

      base.DrawAttack(gameTime);
    }

    public override void DrawConquerMove(GameTime gameTime)
    {
      DrawCenteredMsg(font, "Spostamento di conquista", new Vector2(gameBounds.Center.X, gameBounds.Center.Y), Color.Red, Vector2.One);
      if (gameState.playerStates[(int)gameState.currentPlayer].isHuman)
        nextBtn.DrawCenteredButton(spriteBatch);

      base.DrawConquerMove(gameTime);
    }

    public override void DrawStrategicMove(GameTime gameTime)
    {
      DrawCenteredMsg(font, "Spostamento strategico", new Vector2(gameBounds.Center.X, gameBounds.Center.Y), Color.Red, Vector2.One);
      if (gameState.playerStates[(int)gameState.currentPlayer].isHuman)
        nextBtn.DrawCenteredButton(spriteBatch);

      base.DrawStrategicMove(gameTime);
    }

    public override void DrawPickCard(GameTime gameTime)
    {
      DrawCenteredMsg(font, "Assegnamento carta", new Vector2(gameBounds.Center.X, gameBounds.Center.Y), Color.Red, Vector2.One);
      //nextBtn.DrawCenteredButton(spriteBatch);
    }


    public override void DrawCardsConfirmation(GameTime gameTime)
    {
      if (!(gameState.playerStates[(int)gameState.currentPlayer].isHuman))
        return;

      spriteBatch.Draw(whitePx, gameBounds, Color.Gray);
      int numCards = gameState.playerStates[(int)gameState.currentPlayer].Cards.Count;
      //int firstCardPos = gameBounds.Center.X - (int)(((float)numCards / 2) * CARD_WIDTH);
      int firstCardPos = gameBounds.Center.X - ((numCards / 2) * CARD_WIDTH) - ((numCards % 2) * CARD_WIDTH / 2);
      bool selected = false;
      for (int i = 0; i < numCards; ++i)
      {
        Rectangle cardRect = new Rectangle(firstCardPos + (i * 100), 200, CARD_WIDTH, CARD_HEIGHT);
        var cardMove = gameState.playerStates[(int)gameState.currentPlayer].CurrCardMove;
        if (gameState.playerStates[(int)gameState.currentPlayer].Cards[i].territory.territoryID == cardMove.card1.territory.territoryID)
          selected = true;
        if (gameState.playerStates[(int)gameState.currentPlayer].Cards[i].territory.territoryID == cardMove.card2.territory.territoryID)
          selected = true;
        if (gameState.playerStates[(int)gameState.currentPlayer].Cards[i].territory.territoryID == cardMove.card3.territory.territoryID)
          selected = true;

        DrawCard(cardRect, selected);
      }

      spriteBatch.DrawString(font, "Vuoi giocare le carte selezionate?", new Vector2(gameBounds.Center.X, gameBounds.Center.Y), Color.Blue);

      confirmBtn.DrawCenteredButton(spriteBatch);
      declineBtn.DrawCenteredButton(spriteBatch);
    }

  }
}
